package br.ufrj.ppgi.infovis.forms;

import br.ufrj.ppgi.infovis.forms.GlobalDefs;

import org.mt4j.AbstractMTApplication;
import org.mt4j.components.visibleComponents.shapes.MTEllipse;
import org.mt4j.components.visibleComponents.widgets.MTSvg;
import org.mt4j.util.MT4jSettings;
import org.mt4j.util.math.Vector3D;

import processing.core.PApplet;

/**
 * <p>
 * (Composite) container class for menu handle components, which (via their
 * position) mark the positions of menu rotation/dragging handles. As a child
 * component of a menu they'll be transformed as well and always represent the
 * calculated touch points via their global position.
 * </p>
 */
public class OverlayHandleContainer extends MarkerContainer {
    /* *** Overlay handle container contstants *** */
    /* *** Application *** */
    /** The multitouch application instance */
    private AbstractMTApplication mtApplication;

    /* *** Handles *** */
    /** The handle width set at initialization */
    private float                 handleWidth;

    /** The handle image at north east */
    private MTSvg                 tpNorthEastMarkerSvg;
    /** The handle image at south east */
    private MTSvg                 tpSouthEastMarkerSvg;
    /** The handle image at south west */
    private MTSvg                 tpSouthWestMarkerSvg;
    /** The handle image at north west */
    private MTSvg                 tpNorthWestMarkerSvg;

    /* ***********Constructors*********** */

    /**
     * Constructor. Instantiates a new OverlayHandleContainer instance with four
     * handles.
     * 
     * @param pApplet
     *            the application instance
     * @param parent
     *            the parent abstract overlay
     * @param handleWidth
     *            the calculated handle width
     * @param tpNorthEast
     *            the touch point north east
     * @param tpSouthEast
     *            the touch point south east
     * @param tpSouthWest
     *            the touch point south west
     * @param tpNorthWest
     *            the touch point north west
     */
    public OverlayHandleContainer(PApplet pApplet, AbstractOverlay parent,
            float handleWidth, Vector3D tpNorthEast, Vector3D tpSouthEast,
            Vector3D tpSouthWest, Vector3D tpNorthWest) {

        // Call superclass constructor
        super(pApplet, parent, null, tpNorthEast, null, tpSouthEast, null,
                tpSouthWest, null, tpNorthWest);

        // Set app reference and handle width
        this.mtApplication = (AbstractMTApplication) pApplet;
        this.handleWidth = handleWidth;

        // Initialize
        initialize();

    }

    /* ********Getters & Setters******** */

    /**
     * Returns the north east marker svg component.
     * 
     * @return the tpNorthEastMarkerSvg if set, otherwise null
     */
    public MTSvg getTpNorthEastMarkerSvg() {
        return this.tpNorthEastMarkerSvg;
    }

    /**
     * Returns the south east marker svg component.
     * 
     * @return the tpSouthEastMarkerSvg if set, otherwise null
     */
    public MTSvg getTpSouthEastMarkerSvg() {
        return this.tpSouthEastMarkerSvg;
    }

    /**
     * Returns the south west marker svg component.
     * 
     * @return the tpSouthWestMarkerSvg if set, otherwise null
     */
    public MTSvg getTpSouthWestMarkerSvg() {
        return this.tpSouthWestMarkerSvg;
    }

    /**
     * Returns the north west marker svg component.
     * 
     * @return the tpNorthWestMarkerSvg if set, otherwise null
     */
    public MTSvg getTpNorthWestMarkerSvg() {
        return this.tpNorthWestMarkerSvg;
    }

    /* *********Utility methods********* */
    /**
     * 
     */
    private void initialize() {
        // Add handle marker svgs to every set touch point
        addHandleMarkerSvgs();
    }

    /**
     * Adds a handle marker SVG for every set touch point marker.
     * 
     */
    private void addHandleMarkerSvgs() {
        // Create touch points marker circles and add as children
        // Svg for North east marker
        if (getTpNorthEastMarker() != null) {
            this.tpNorthEastMarkerSvg = addSingleHandleMarkerSvg(getTpNorthEastMarker());
        }

        // Svg for South east marker
        if (getTpSouthEastMarker() != null) {
            this.tpSouthEastMarkerSvg = addSingleHandleMarkerSvg(getTpSouthEastMarker());
        }

        // Svg for South west marker
        if (getTpSouthWestMarker() != null) {
            this.tpSouthWestMarkerSvg = addSingleHandleMarkerSvg(getTpSouthWestMarker());
        }

        // Svg for North west marker
        if (getTpNorthWestMarker() != null) {

            this.tpNorthWestMarkerSvg = addSingleHandleMarkerSvg(getTpNorthWestMarker());
        }
    }

    /**
     * <p>
     * Adds a single handle SVG as child to the specified marker.
     * </p>
     * <p>
     * Don't forget to assign the result to the associated member!
     * </p>
     * 
     * 
     * @param marker
     *            the marker to add the MTSvg to
     * @return the handle MTSvg instance
     */
    private MTSvg addSingleHandleMarkerSvg(MTEllipse marker) {
        // Create new SVG component
        MTSvg handleSvg = new MTSvg(getAbstractMTapplication(), GlobalDefs.OVERLAY_HANDLE_IMG_NAME);

        // Get marker global position
        Vector3D position = marker.getCenterPointGlobal();

        // Position at specified touch point marker center
        handleSvg.setPositionGlobal(position);

        // Set scale (parent Overlay width / Overlay handle scaling factor)
        handleSvg.setWidthXYGlobal(this.handleWidth);

        marker.addChild(handleSvg);
        return handleSvg;
    }
}
